#ifndef __M_EXCHANGE_H__
#define __M_EXCHANGE_H__
// 引入基础组件头文件
#include "../mqcommon/mq_logger.hpp" // 日志工具
#include "../mqcommon/mq_helper.hpp" // 字符串/文件工具
#include "../mqcommon/mq_msg.pb.h"   // Protobuf 消息定义
#include <google/protobuf/map.h>     // Protobuf Map 类型
#include <iostream>
#include <unordered_map> // 无序映射（内存存储）
#include <mutex>         // 互斥锁（线程安全）
#include <memory>        // 智能指针（内存管理）

namespace zdfmq
{

    // ====================== 1. 交换机核心模型定义 ======================
    struct Exchange
    {
        using ptr = std::shared_ptr<Exchange>; // 智能指针别名，简化 shared_ptr 用法

        // 交换机核心属性
        std::string name;  // 交换机名称（唯一标识）
        ExchangeType type; // 交换机类型（DIRECT/FANOUT/TOPIC 等）
        bool durable;      // 是否持久化（重启后保留元数据）
        bool auto_delete;  // 无队列绑定时是否自动删除
        // 扩展参数（使用 Protobuf Map，兼容协议缓冲区序列化）
        google::protobuf::Map<std::string, std::string> args;

        // 无参构造函数（用于反序列化场景）
        Exchange() {}

        // 带参构造函数（创建交换机时初始化）
        Exchange(const std::string &ename,
                 ExchangeType etype,
                 bool edurable,
                 bool eauto_delete,
                 const google::protobuf::Map<std::string, std::string> &eargs)
            : name(ename), type(etype), durable(edurable),
              auto_delete(eauto_delete), args(eargs) {}

        // ====================== 参数序列化与反序列化 ======================
        // 从格式化字符串解析参数（用于数据库恢复）
        void setArgs(const std::string &str_args)
        {
            std::vector<std::string> sub_args;
            // 按 & 分割字符串（如 "k1=v1&k2=v2" → ["k1=v1", "k2=v2"]）
            StrHelper::split(str_args, "&", sub_args);
            for (auto &str : sub_args)
            {
                size_t pos = str.find("=");
                if (pos == std::string::npos)
                    continue; // 格式错误跳过
                std::string key = str.substr(0, pos);
                std::string val = str.substr(pos + 1);
                args[key] = val; // 存入 Protobuf Map
            }
        }

        // 将参数序列化为字符串（用于存入数据库）
        std::string getArgs()
        {
            std::string result;
            // 遍历 Protobuf Map，拼接成 key=val&key=val 格式
            for (auto it = args.begin(); it != args.end(); ++it)
            {
                result += it->first + "=" + it->second + "&";
            }
            return result;
        }
    };

    // 内存中交换机的映射：名称 → 交换机智能指针
    using ExchangeMap = std::unordered_map<std::string, Exchange::ptr>;

    // ====================== 2. 交换机持久化映射器（对接 SQLite 数据库） ======================
    class ExchangeMapper
    {
    public:
        // 构造函数：初始化数据库连接并创建表
        ExchangeMapper(const std::string &dbfile) : _sql_helper(dbfile)
        {
            // 创建数据库所在目录（确保路径存在）
            std::string path = FileHelper::parentDirectory(dbfile);
            FileHelper::createDirectory(path);
            // 打开数据库连接（断言确保成功，失败则终止）
            assert(_sql_helper.open());
            // 确保交换机表存在
            createTable();
        }

        // 创建交换机表（若不存在）
        void createTable()
        {
// 定义建表 SQL：包含名称、类型、持久化等字段
#define CREATE_TABLE "create table if not exists exchange_table(\
            name varchar(32) primary key, \
            type int, \
            durable int, \
            auto_delete int, \
            args varchar(128));"
            bool ret = _sql_helper.exec(CREATE_TABLE, nullptr, nullptr);
            if (!ret)
            {
                DLOG("创建交换机数据库表失败！！");
                abort(); // 严重错误，直接终止程序
            }
        }

        // 删除交换机表（测试/清理场景用）
        void removeTable()
        {
#define DROP_TABLE "drop table if exists exchange_table;"
            bool ret = _sql_helper.exec(DROP_TABLE, nullptr, nullptr);
            if (!ret)
            {
                DLOG("删除交换机数据库表失败！！");
                abort(); // 严重错误，直接终止程序
            }
        }

        // 插入交换机元数据到数据库
        bool insert(Exchange::ptr &exp)
        {
            std::stringstream sql;
            sql << "insert into exchange_table values("
                << "'" << exp->name << "', "      // 字符串字段用单引号包裹
                << exp->type << ", "              // 枚举类型存 int
                << (exp->durable ? 1 : 0) << ", " // bool 转 int 存储
                << (exp->auto_delete ? 1 : 0) << ", "
                << "'" << exp->getArgs() << "');"; // 序列化后的参数字符串
            return _sql_helper.exec(sql.str(), nullptr, nullptr);
        }

        // 从数据库删除指定交换机
        void remove(const std::string &name)
        {
            std::stringstream sql;
            sql << "delete from exchange_table where name='" << name << "';";
            _sql_helper.exec(sql.str(), nullptr, nullptr);
        }

        // 从数据库恢复所有交换机到内存
        ExchangeMap recovery()
        {
            ExchangeMap result;
            std::string sql = "select name, type, durable, auto_delete, args from exchange_table;";
            // 执行查询，用回调函数处理结果集
            _sql_helper.exec(sql, selectCallback, &result);
            return result;
        }

    private:
        // 结果集回调函数：将数据库行转换为 Exchange 对象
        static int selectCallback(void *arg, int numcol, char **row, char **fields)
        {
            ExchangeMap *result = (ExchangeMap *)arg; // 传入的 result 作为输出容器
            auto exp = std::make_shared<Exchange>();
            // 按数据库字段顺序解析
            exp->name = row[0];                                 // 第 0 列：名称
            exp->type = (zdfmq::ExchangeType)std::stoi(row[1]); // 第 1 列：类型（int 转枚举）
            exp->durable = std::stoi(row[2]);                   // 第 2 列：持久化（int 转 bool）
            exp->auto_delete = std::stoi(row[3]);               // 第 3 列：自动删除
            if (row[4])
            {                         // 第 4 列：参数字符串（可能为 NULL）
                exp->setArgs(row[4]); // 反序列化为 Protobuf Map
            }
            // 存入内存映射（名称为键）
            result->insert({exp->name, exp});
            return 0; // 回调返回 0 表示成功处理
        }

    private:
        SqliteHelper _sql_helper; // SQLite 数据库操作助手（封装了基本 SQL 执行）
    };

    // ====================== 3. 交换机内存管理器（业务逻辑层） ======================
    class ExchangeManager
    {
    public:
        using ptr = std::shared_ptr<ExchangeManager>; // 智能指针别名

        // 构造函数：从数据库恢复交换机到内存
        ExchangeManager(const std::string &dbfile) : _mapper(dbfile)
        {
            _exchanges = _mapper.recovery(); // 加载数据库中所有交换机
        }

        // 声明（创建）交换机：支持幂等性（存在则直接返回 true）
        bool declareExchange(const std::string &name,
                             ExchangeType type, bool durable, bool auto_delete,
                             const google::protobuf::Map<std::string, std::string> &args)
        {
            std::unique_lock<std::mutex> lock(_mutex); // 加锁保证线程安全
            auto it = _exchanges.find(name);
            if (it != _exchanges.end())
            {
                return true; // 交换机已存在，声明成功
            }

            // 创建新交换机对象
            auto exp = std::make_shared<Exchange>(name, type, durable, auto_delete, args);

            // 持久化逻辑：仅当 durable 为 true 时写入数据库
            if (durable)
            {
                bool ret = _mapper.insert(exp);
                if (!ret)
                {
                    return false; // 持久化失败，声明失败
                }
            }

            // 存入内存映射
            _exchanges.insert({name, exp});
            return true;
        }

        // 删除交换机：内存和数据库（若持久化）都删除
        void deleteExchange(const std::string &name)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _exchanges.find(name);
            if (it == _exchanges.end())
            {
                return; // 交换机不存在，无需删除
            }

            // 持久化删除：若交换机是持久化的，从数据库删除
            if (it->second->durable)
            {
                _mapper.remove(name);
            }

            // 内存中删除交换机
            _exchanges.erase(it);
        }

        // 查询交换机：返回智能指针（空指针表示不存在）
        Exchange::ptr selectExchange(const std::string &name)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _exchanges.find(name);
            if (it == _exchanges.end())
            {
                return Exchange::ptr(); // 返回空智能指针
            }
            return it->second;
        }

        // 检查交换机是否存在
        bool exists(const std::string &name)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            return _exchanges.count(name) > 0;
        }

        // 获取交换机总数
        size_t size()
        {
            std::unique_lock<std::mutex> lock(_mutex);
            return _exchanges.size();
        }

        // 清理所有交换机：删除数据库表 + 清空内存
        void clear()
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _mapper.removeTable();
            _exchanges.clear();
        }

    private:
        std::mutex _mutex;      // 互斥锁，保证多线程安全
        ExchangeMapper _mapper; // 持久化操作器（对接数据库）
        ExchangeMap _exchanges; // 内存中交换机的映射（名称为键）
    };

} // namespace zdfmq

#endif // __M_EXCHANGE_H__